
package cell

import (
	"github.com/treelab/updatecolumn/models"
)

// InstanceType of cell
func InstanceType() int32 {
	return models.Select
}


  //#region CellValueConvert
  cellValueToString({ column, cell }: IColumnAndCell) {
    const options = this.getSelectedOption({ column, cell });
    return options.length ? options.map(option => `${option!.name}`).join(', ') : '';
  }

  cellValueToNumber({ column, cell }: IColumnAndCell) {
    const options = this.getSelectedOption({ column, cell });
    const result = options.length
      ? parseFloat(
          _.join(
            options.map((option: any) => `${option.name}`),
            '',
          ).replace(/[^0-9.-]/g, ''),
        )
      : 0;
    return isNaN(result) ? 0 : result;
  }

  cellValueToSelect({ column, cell }: IColumnAndCell) {
    const options = this.getSelectedOption({ column, cell });
    return options.length ? options[0] : undefined;
  }

  cellValueToMultiSelect({ cell, column }: IColumnAndCell) {
    const options = this.getSelectedOption({ column, cell });
    return options || options;
  }

  cellValueToCollaborator({ cell, column, userGroup }: { cell: Cell; column: Column; userGroup: any }) {
    const userGroups = userGroup?.groups || [];
    const groups = [];
    const selectArray = this.getSelectedOption({ column, cell });
    if (selectArray && selectArray.length > 0) {
      const text = selectArray[0].name;
      const find = this.findCollaboratorGroupAndUser(userGroups, text, ['name', 'phoneNumber', 'email']);
      if (find) {
        groups.push(find);
      }
    }
    return groups;
  }

  cellValueToRating({ column, cell }: IColumnAndCell) {
    let finalRating = 0;
    const options = this.getSelectedOption({ column, cell });
    const finalNum = options ? options.map((option: any) => `${option.name}`) : [];
    if (!_.isNaN(Number(finalNum[0]))) {
      finalRating = Math.round(Number(finalNum[0]));
    }
    return finalRating;
  }

  cellValueToDatetime({ column, cell }: IColumnAndCell) {
    const options = this.getSelectedOption({ column, cell });
    const selectText = options.map(option => ` ${option!.name}`);
    return selectText ? selectText[0]?.trim() : '';
  }

  cellValueToCheckbox({ column, cell }: IColumnAndCell) {
    const options = this.getSelectedOption({ column, cell });
    if (options.length) {
      const finalNum = options.map((option: any) => `${option.name}`);
      return finalNum[0] === 'true' || finalNum[0] === 'checked';
    }
    return false;
  }
  //#endregion

  setCellValue({ column, cell, action, isNewCell }: ICCAction, o: CommonOptions) {
    if (cell.uid && !isNewCell) {
      this.removeInvalidCellOption({ column, cell }, o);
    }
    const selectOption = (action.value as SelectCellValue).selectedOption!;
    if (selectOption) {
      const findOption = (cell.hasColumnOption.get() || []).find((option: any) => option.uid === selectOption.uid);
      if (!findOption) {
        // remove the currently selected option
        const currentlySelectedOption = cell.hasColumnOption.get()[0];
        if (currentlySelectedOption) {
          o.delQuads.push(`<${cell.uid!}> <${Relation.HAS_COLUMN_OPTION}> <${currentlySelectedOption.uid}> .`);
        }
        remove((cell.hasColumnOption as any)._data, ({ uid }) => uid === currentlySelectedOption.uid);
        // add newly selected option
        cell.hasColumnOption.add(selectOption);
        (action.value as SelectCellValue).selectedOptionId = this.getNodeTempId(selectOption);
      }
    }
    delete (action.value as SelectCellValue).selectedOption;
    return this;
  }

  getCellValue(cell: CellData) {
    return _.get(cell, 'options[0].id');
  }

  convertCell(
    command: UpdateColumn_v2,
    o: CommonOptions,
    { columnCopy, referenceColumns, userGroup }: { columnCopy: Column; referenceColumns?: Column[]; userGroup: any[] },
  ) {
    const { column } = command;
    const { columnType: fromType } = columnCopy;
    const cells = column.hasCell.get();
    const events = new EventHelper();
    if (this.needEmptyCell({ ...command, column: columnCopy })) {
      const fromCellHandle = this.instanceFactory.getCellInstance(fromType as ColumnType);
      fromCellHandle.emptyCells(command, cells, false, o);
    }
    if (cells.length) {
      const visableNameMapping = new Map<string, string>();
      _.forEach(cells, cell => {
        const action = this.getAction(command, columnCopy, cell, userGroup);
        const rowData = this.upsertCell(
          cell,
          {
            command: {
              ...command,
              action,
              _metadata: { ...command._metadata, source: Source.SAGA },
            },
          },
          { ...o, events },
          { columnCopy },
        );
        if (rowData) {
          visableNameMapping.set(rowData.uid, rowData.visibleName);
        }
      });
      this.updateReferenceColumnAndDependencies({
        column,
        visableNameMapping,
        o,
        _metadata: command._metadata,
        referenceColumns,
      });
    }

    o.events.bulkAddEvents(...events);
    return this;
  }

  protected getAction(command: UpdateColumn_v2, fromColumn: Column, cell: Cell, userGroup?: any) {
    const { column, columnConfig } = command;
    const { type: toType } = columnConfig;
    const { columnType: fromType } = fromColumn;

    const action: any = {
      type: UpdateAction.SET_VALUE,
      value: { ...command.columnConfig, type: toType },
    };
    delete action.value.options;

    const value = action.value as SelectCellValue;
    const fromCellHandle = this.instanceFactory.getCellInstance(fromType as ColumnType);
    value.selectedOption = fromCellHandle.cellValueToSelect({ column, cell, userGroup });
    if (value.selectedOption) {
      value.selectedOptionId = value.selectedOption?.uid ?? this.getNodeTempId(value.selectedOption);
    } else {
      delete value.selectedOption;
    }
    return action;
  }

  protected addCellUpdateEvent(command: UpdateCell_v2, cell: Cell, o: CommonOptions) {
    const { workspaceId, coreId, tableId, action, _metadata } = command!;
    const cellId = cell.uid ?? this.getNodeTempId(cell);
    o!.events.addEvents(
      new CellUpdated(workspaceId, coreId, tableId, cell.columnId, cell.rowId, cellId, action, _metadata),
      ['cellId', 'selectedOptionId'],
    );
  }

  emptyCells(command: UpdateColumn_v2, cells: readonly Cell[], deleteCells: boolean, o: CommonOptions) {
    if (!deleteCells) {
      _.forEach(cells, cell => {
        o.delQuads.push(...this.dgraphHelperService.getRemoveEdgeQuads(cell.uid!, Relation.HAS_COLUMN_OPTION));
      });
    }
    super.emptyCells(command, cells, deleteCells, o);
    return this;
  }

  protected needEmptyCell(command?: UpdateColumn_v2) {
    return ![ColumnType.MULTI_SELECT, ColumnType.SELECT].includes(command?.column.columnType!);
  }

  protected getAddCellOptionQuad(cell: Cell, optionIds: string[], o: CommonOptions) {
    _.forEach(optionIds, optionId => {
      if (optionId) {
        const cellOption = o.ormTransaction.nodeFor(ColumnOption, { uid: optionId });
        cell.hasColumnOption.add(cellOption);
      }
    });
  }

  protected getRemoveCellOptionsQuad(cellId: string): string[] {
    return this.dgraphHelperService.getRemoveEdgeQuads(cellId, Relation.HAS_COLUMN_OPTION);
  }

  protected removeInvalidCellOption({ column, cell }: { column: Column; cell: Cell }, o: CommonOptions) {
    const cellOption = cell.hasColumnOption.get();
    const columnOption = column.hasColumnOption.get();

    const removeCellOptions = _.differenceBy(cellOption, columnOption, 'uid');
    if (removeCellOptions.length) {
      _.forEach(removeCellOptions, removeCellOption => {
        o.delQuads.push(
          ...this.dgraphHelperService.getRemoveEdgeQuads(cell.uid!, Relation.HAS_COLUMN_OPTION, removeCellOption.uid),
        );
        cell.hasColumnOption.delete(removeCellOption);
      });
    }
  }

